/**
 * Map工具类，封装了一些使用Map数据结构的常用操作
 */
export class MapWrapper<K, V> {
  private __map: Map<K, V>;

  /**
   * 构造函数
   * @param {readonly (readonly [K, V])[] | undefined} entries 可选的初始键值对数组
   * @example
   * // 创建一个空的MapWrapper
   * const emptyMap = new MapWrapper<number, string>();
   * 
   * // 创建带有初始数据的MapWrapper
   * const mapWithData = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   */
  constructor(entries?: readonly (readonly [K, V])[]) {
    this.__map = new Map(entries);
  }

  /**
   * 获取内部Map实例
   * @returns {Map<K, V>} 内部的Map实例
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one']]);
   * const internalMap = map.getMap(); // 返回原生Map对象
   */
  getMap(): Map<K, V> {
    return this.__map;
  }

  /**
   * 添加或更新键值对
   * @param {K} key 键
   * @param {V} value 值
   * @returns {this} 返回MapWrapper实例，支持链式调用
   * @example
   * const map = new MapWrapper<number, string>();
   * map.set(1, 'one').set(2, 'two'); // 链式调用
   */
  set(key: K, value: V): this {
    this.__map.set(key, value);
    return this;
  }

  /**
   * 添加多个键值对
   * @param {Array<readonly [K, V]>} entries 键值对数组
   * @returns {this} 返回MapWrapper实例，支持链式调用
   * @example
   * const map = new MapWrapper<number, string>();
   * map.setMultiple([[1, 'one'], [2, 'two']]);
   */
  setMultiple(entries: (readonly [K, V])[]): this {
    entries.forEach(([key, value]) => this.__map.set(key, value));
    return this;
  }

  /**
   * 获取指定键的值
   * @param {K} key 键
   * @param {V} [defaultValue] 当键不存在时返回的默认值
   * @returns {V | undefined} 键对应的值或默认值
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one']]);
   * console.log(map.get(1)); // 'one'
   * console.log(map.get(2)); // undefined
   * console.log(map.get(2, 'default')); // 'default'
   */
  get(key: K, defaultValue?: V): V | undefined {
    return this.__map.has(key) ? this.__map.get(key) : defaultValue;
  }

  /**
   * 获取指定键的值，若不存在则设置默认值
   * @param {K} key 键
   * @param {V} defaultValue 当键不存在时返回的默认值，并且会设置该默认值
   * @returns {V} 键对应的值或默认值
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one']]);
   * console.log(map.gset(1, 'default')); // 'one'
   * console.log(map.gset(2, 'default')); // 'default'
   */
  gset(key: K, defaultValue: V): V {
    if (!this.__map.has(key)) {
      this.__map.set(key, defaultValue);
    }
    return this.__map.get(key)!;
  }

  /**
   * 设置指定键的值，并且返回该值
   * @param {K} key 键
   * @param {V} value 值
   * @returns {V} 键对应的值或默认值
   * @example
   * const map = new MapWrapper<number, string>();
   * console.log(map.sget(1, 'one')); // 'one'
   */
  sget(key: K, value: V): V {
    this.__map.set(key, value);
    return value;
  }

  /**
   * 检查是否包含指定键
   * @param {K} key 键
   * @returns {boolean} 是否包含指定键
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one']]);
   * console.log(map.has(1)); // true
   * console.log(map.has(2)); // false
   */
  has(key: K): boolean {
    return this.__map.has(key);
  }

  /**
   * 检查是否包含指定值
   * @param {V} value 值
   * @returns {boolean} 是否包含指定值
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one']]);
   * console.log(map.hasValue('one')); // true
   * console.log(map.hasValue('two')); // false
   */
  hasValue(value: V): boolean {
    return Array.from(this.__map.values()).includes(value);
  }

  /**
   * 删除指定键值对
   * @param {K} key 键
   * @returns {boolean} 是否成功删除（键是否存在）
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one']]);
   * console.log(map.delete(1)); // true
   * console.log(map.delete(2)); // false
   */
  delete(key: K): boolean {
    return this.__map.delete(key);
  }

  /**
   * 删除多个键值对
   * @param {K[]} keys 键数组
   * @returns {K[]} 成功删除的键数组
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two'], [3, 'three']]);
   * map.deleteMultiple([1, 3]); // 删除键为1和3的键值对
   */
  deleteMultiple(keys: K[]): K[] {
    // 过滤出存在的键
    const existingKeys = keys.filter(key => this.__map.has(key));

    existingKeys.forEach(key => this.__map.delete(key));
    return existingKeys;
  }

  /**
   * 清空Map
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one']]);
   * map.clear(); // Map变为空
   */
  clear(): void {
    this.__map.clear();
  }

  /**
   * 获取Map的大小
   * @returns {number} Map中键值对的数量
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * console.log(map.size()); // 2
   */
  size(): number {
    return this.__map.size;
  }

  /**
   * 检查Map是否为空
   * @returns {boolean} Map是否为空
   * @example
   * const emptyMap = new MapWrapper<number, string>();
   * console.log(emptyMap.isEmpty()); // true
   * 
   * const mapWithData = new MapWrapper<number, string>([[1, 'one']]);
   * console.log(mapWithData.isEmpty()); // false
   */
  isEmpty(): boolean {
    return this.__map.size === 0;
  }

  /**
   * 获取所有键的数组
   * @returns {K[]} 包含所有键的数组
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * console.log(map.keys()); // [1, 2]
   */
  keys(): K[] {
    return Array.from(this.__map.keys());
  }

  /**
   * 获取所有值的数组
   * @returns {V[]} 包含所有值的数组
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * console.log(map.values()); // ['one', 'two']
   */
  values(): V[] {
    return Array.from(this.__map.values());
  }

  /**
   * 获取所有键值对的数组
   * @returns {Array<[K, V]>} 包含所有键值对的数组
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * console.log(map.entries()); // [[1, 'one'], [2, 'two']]
   */
  entries(): [K, V][] {
    return Array.from(this.__map.entries());
  }

  /**
   * 对Map中的每个键值对执行回调函数
   * @param {(value: V, key: K, map: Map<K, V>) => void} callback 回调函数
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * map.forEach((value, key) => {
   *   console.log(`${key}: ${value}`);
   * });
   * // 输出: 
   * // 1: one
   * // 2: two
   */
  forEach(callback: (value: V, key: K, map: Map<K, V>) => void): void {
    this.__map.forEach(callback);
  }

  /**
   * 根据回调函数过滤Map
   * @param {(value: V, key: K) => boolean} predicate 过滤条件回调函数
   * @returns {MapWrapper<K, V>} 过滤后的新MapWrapper实例
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two'], [3, 'three']]);
   * const filtered = map.filter((value, key) => key > 1);
   * console.log(filtered.entries()); // [[2, 'two'], [3, 'three']]
   */
  filter(predicate: (value: V, key: K) => boolean): MapWrapper<K, V> {
    const filteredMap = new MapWrapper<K, V>();
    this.forEach((value, key) => {
      if (predicate(value, key)) {
        filteredMap.set(key, value);
      }
    });
    return filteredMap;
  }

  /**
   * 对Map中的每个值执行映射函数
   * @template T
   * @param {(value: V, key: K) => T} mapper 映射函数
   * @returns {MapWrapper<K, T>} 映射后的新MapWrapper实例
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * const lengthsMap = map.mapValues(value => value.length);
   * console.log(lengthsMap.entries()); // [[1, 3], [2, 3]]
   */
  mapValues<T>(mapper: (value: V, key: K) => T): MapWrapper<K, T> {
    const mappedMap = new MapWrapper<K, T>();
    this.forEach((value, key) => {
      mappedMap.set(key, mapper(value, key));
    });
    return mappedMap;
  }

  /**
   * 对Map中的所有值执行归约操作
   * @template T
   * @param {(accumulator: T, value: V, key: K) => T} reducer 归约函数
   * @param {T} initialValue 初始值
   * @returns {T} 归约结果
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * const concatenated = map.reduce((acc, value) => acc + value, '');
   * console.log(concatenated); // 'onetwo'
   */
  reduce<T>(reducer: (accumulator: T, value: V, key: K) => T, initialValue: T): T {
    let accumulator = initialValue;
    this.forEach((value, key) => {
      accumulator = reducer(accumulator, value, key);
    });
    return accumulator;
  }

  /**
   * 检查Map中的所有元素是否满足条件
   * @param {(value: V, key: K) => boolean} predicate 条件函数
   * @returns {boolean} 是否所有元素都满足条件
   * @example
   * const map = new MapWrapper<number, number>([[1, 10], [2, 20], [3, 30]]);
   * console.log(map.every(value => value > 5)); // true
   * console.log(map.every(value => value > 15)); // false
   */
  every(predicate: (value: V, key: K) => boolean): boolean {
    for (const [key, value] of this.__map) {
      if (!predicate(value, key)) {
        return false;
      }
    }
    return true;
  }

  /**
   * 检查Map中是否至少有一个元素满足条件
   * @param {(value: V, key: K) => boolean} predicate 条件函数
   * @returns {boolean} 是否至少有一个元素满足条件
   * @example
   * const map = new MapWrapper<number, number>([[1, 10], [2, 20], [3, 30]]);
   * console.log(map.some(value => value > 25)); // true
   * console.log(map.some(value => value > 40)); // false
   */
  some(predicate: (value: V, key: K) => boolean): boolean {
    for (const [key, value] of this.__map) {
      if (predicate(value, key)) {
        return true;
      }
    }
    return false;
  }

  /**
   * 查找第一个满足条件的键值对
   * @param {(value: V, key: K) => boolean} predicate 条件函数
   * @returns {Array<[K, V]> | undefined} 找到的键值对或undefined
   * @example
   * const map = new MapWrapper<number, number>([[1, 10], [2, 20], [3, 30]]);
   * const found = map.find((value, key) => key > 1);
   * console.log(found); // [2, 20]
   */
  find(predicate: (value: V, key: K) => boolean): [K, V] | undefined {
    for (const [key, value] of this.__map) {
      if (predicate(value, key)) {
        return [key, value];
      }
    }
    return undefined;
  }

  /**
   * 合并两个Map
   * @param {Map<K, V> | MapWrapper<K, V>} otherMap 另一个Map或MapWrapper实例
   * @param {boolean} [overwrite=true] 是否覆盖已存在的键值对
   * @returns {this} 返回当前MapWrapper实例，支持链式调用
   * @example
   * const map1 = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * const map2 = new MapWrapper<number, string>([[2, 'TWO'], [3, 'three']]);
   * 
   * // 覆盖已存在的键
   * map1.merge(map2);
   * console.log(map1.entries()); // [[1, 'one'], [2, 'TWO'], [3, 'three']]
   * 
   * // 不覆盖已存在的键
   * map1.merge(map2, false);
   * console.log(map1.entries()); // [[1, 'one'], [2, 'two'], [3, 'three']]
   */
  merge(otherMap: Map<K, V> | MapWrapper<K, V>, overwrite: boolean = true): this {
    const entries = otherMap instanceof MapWrapper ? otherMap.entries() : Array.from(otherMap.entries());

    entries.forEach(([key, value]) => {
      if (overwrite || !this.has(key)) {
        this.set(key, value);
      }
    });

    return this;
  }

  /**
   * 将Map转换为对象
   * 注意：只有当键是string或number时才能正确转换
   * @returns {Record<string, V>} 转换后的对象
   * @example
   * const map = new MapWrapper<number, string>([[1, 'one'], [2, 'two']]);
   * console.log(map.toObject()); // { '1': 'one', '2': 'two' }
   */
  toObject(): Record<string, V> {
    const obj: Record<string, V> = {};
    this.forEach((value, key) => {
      obj[String(key)] = value;
    });
    return obj;
  }

  /**
   * 从对象创建MapWrapper实例
   * @template K, V
   * @param {Record<K, V>} obj 源对象
   * @returns {MapWrapper<K, V>} 新的MapWrapper实例
   * @example
   * const obj = { 1: 'one', 2: 'two' };
   * const map = MapWrapper.fromObject(obj);
   * console.log(map.entries()); // [[1, 'one'], [2, 'two']]
   */
  fromObject<K extends string | number, V>(obj: Record<K, V>): MapWrapper<K, V> {
    const map = new MapWrapper<K, V>();
    Object.entries(obj).forEach(([key, value]) => {
      map.set(key as K, value as V);
    });
    return map;
  }

  /**
   * 创建MapWrapper的浅拷贝
   * @returns {MapWrapper<K, V>} 新的MapWrapper实例
   * @example
   * const original = new MapWrapper<number, string>([[1, 'one']]);
   * const clone = original.clone();
   * console.log(clone.entries()); // [[1, 'one']]
   * console.log(original !== clone); // true
   */
  clone(): MapWrapper<K, V> {
    return new MapWrapper<K, V>(this.entries());
  }

  /**
   * 根据键对Map进行排序
   * @param {(a: K, b: K) => number} [comparator] 比较函数
   * @returns {MapWrapper<K, V>} 排序后的新MapWrapper实例
   * @example
   * const map = new MapWrapper<string, number>([['c', 3], ['a', 1], ['b', 2]]);
   * const sorted = map.sortByKey();
   * console.log(sorted.entries()); // [['a', 1], ['b', 2], ['c', 3]]
   * 
   * // 使用自定义比较函数
   * const reverseSorted = map.sortByKey((a, b) => b.localeCompare(a));
   * console.log(reverseSorted.entries()); // [['c', 3], ['b', 2], ['a', 1]]
   */
  sortByKey(comparator?: (a: K, b: K) => number): MapWrapper<K, V> {
    const sortedEntries = this.entries().sort(([aKey], [bKey]) => {
      if (comparator) {
        return comparator(aKey, bKey);
      }
      // 默认字符串比较
      if (typeof aKey === 'string' && typeof bKey === 'string') {
        return aKey.localeCompare(bKey);
      }
      // 默认数字比较
      if (typeof aKey === 'number' && typeof bKey === 'number') {
        return aKey - bKey;
      }
      // 转换为字符串后比较
      return String(aKey).localeCompare(String(bKey));
    });

    return new MapWrapper<K, V>(sortedEntries);
  }

  /**
   * 根据值对Map进行排序
   * @param {(a: V, b: V) => number} [comparator] 比较函数
   * @returns {MapWrapper<K, V>} 排序后的新MapWrapper实例
   * @example
   * const map = new MapWrapper<string, number>([['a', 3], ['b', 1], ['c', 2]]);
   * const sorted = map.sortByValue();
   * console.log(sorted.entries()); // [['b', 1], ['c', 2], ['a', 3]]
   * 
   * // 使用自定义比较函数
   * const reverseSorted = map.sortByValue((a, b) => b - a);
   * console.log(reverseSorted.entries()); // [['a', 3], ['c', 2], ['b', 1]]
   */
  sortByValue(comparator?: (a: V, b: V) => number): MapWrapper<K, V> {
    const sortedEntries = this.entries().sort(([, aValue], [, bValue]) => {
      if (comparator) {
        return comparator(aValue, bValue);
      }
      // 默认比较
      if (aValue < bValue) return -1;
      if (aValue > bValue) return 1;
      return 0;
    });

    return new MapWrapper<K, V>(sortedEntries);
  }

  /**
   * 获取Map中值的最大值
   * @param {(value: V) => number} [extractor] 可选的值提取函数
   * @returns {V | undefined} 值最大的元素或undefined（如果Map为空）
   * @example
   * const map = new MapWrapper<string, number>([['a', 10], ['b', 30], ['c', 20]]);
   * console.log(map.maxValue()); // 30
   * 
   * // 使用提取函数
   * const objMap = new MapWrapper<string, { value: number }>([
   *   ['a', { value: 10 }],
   *   ['b', { value: 30 }],
   *   ['c', { value: 20 }]
   * ]);
   * console.log(map.maxValue(item => item.value)); // { value: 30 }
   */
  maxValue(extractor?: (value: V) => number): V | undefined {
    if (this.isEmpty()) return undefined;

    let max: V | undefined;
    let maxExtracted: number | undefined;

    this.forEach((value) => {
      const extracted = extractor ? extractor(value) : (value as unknown as number);
      if (maxExtracted === undefined || extracted > maxExtracted) {
        max = value;
        maxExtracted = extracted;
      }
    });

    return max;
  }

  /**
   * 获取Map中值的最小值
   * @param {(value: V) => number} [extractor] 可选的值提取函数
   * @returns {V | undefined} 值最小的元素或undefined（如果Map为空）
   * @example
   * const map = new MapWrapper<string, number>([['a', 10], ['b', 30], ['c', 20]]);
   * console.log(map.minValue()); // 10
   * 
   * // 使用提取函数
   * const objMap = new MapWrapper<string, { value: number }>([
   *   ['a', { value: 10 }],
   *   ['b', { value: 30 }],
   *   ['c', { value: 20 }]
   * ]);
   * console.log(map.minValue(item => item.value)); // { value: 10 }
   */
  minValue(extractor?: (value: V) => number): V | undefined {
    if (this.isEmpty()) return undefined;

    let min: V | undefined;
    let minExtracted: number | undefined;

    this.forEach((value) => {
      const extracted = extractor ? extractor(value) : (value as unknown as number);
      if (minExtracted === undefined || extracted < minExtracted) {
        min = value;
        minExtracted = extracted;
      }
    });

    return min;
  }
}